#include <stdio.h>
#include "ADuCM4050.h"
#include "drivers/gpio/adi_gpio.h"
#include "drivers/i2c/adi_i2c.h"
#include "drivers/uart/adi_uart.h"
#include "drivers/xint/adi_xint.h "
#include "drivers/tmr/adi_tmr.h"
#include "drivers/spi/adi_spi.h"
#include "drivers/pwr/adi_pwr.h"
#include "GPIO.h"
#include "DELAY.h"
#include "PITCH.h"
#include "MUSIC_NOTE.h"

unsigned char GPIO_MemorySize[ADI_GPIO_MEMORY_SIZE]; //16b
unsigned char XINT_MemorySize[ADI_XINT_MEMORY_SIZE]; //48b
unsigned char I2C_MemorySize[ADI_I2C_MEMORY_SIZE]; //48b
unsigned char SPI_MemorySize[ADI_SPI_MEMORY_SIZE]; //48b
unsigned char UART_MemorySize[ADI_UART_BIDIR_MEMORY_SIZE]; //双向内存

void init_GPIO(void)
{
	adi_gpio_Init(&GPIO_MemorySize,ADI_GPIO_MEMORY_SIZE);
	adi_gpio_OutputEnable(Port0,Pin0,true);
	adi_gpio_PullUpEnable(Port0,Pin0,true);	
	adi_gpio_DriveStrengthEnable(Port0,Pin0,true);
	adi_gpio_InputEnable(Port0,Pin1,true);  //使能输入
	
	adi_gpio_OutputEnable(Port0,Pin13,true);
	adi_gpio_PullUpEnable(Port0,Pin13,false);
	adi_gpio_DriveStrengthEnable(Port0,Pin13,true);
	
	adi_gpio_OutputEnable(Port0,Pin8,true);
	adi_gpio_PullUpEnable(Port0,Pin8,false);
	adi_gpio_DriveStrengthEnable(Port0,Pin8,true);
	
	adi_gpio_OutputEnable(Port0,Pin9,true);
	adi_gpio_PullUpEnable(Port0,Pin9,false);
	adi_gpio_DriveStrengthEnable(Port0,Pin9,true);
	
	adi_gpio_InputEnable(Port2,Pin9,true);  //使能输入
	
	adi_gpio_SetGroupInterruptPins(Port0,ADI_GPIO_INTA_IRQ,Pin1);
//	adi_gpio_SetGroupInterruptPolarity(Port0,Pin1);
	adi_gpio_GroupInterruptPolarityEnable(Port0,Pin1,false);
}

//外部中断回调函数
ADI_CALLBACK callback_XINT0(void)
{
	adi_gpio_Toggle(Port0,Pin0);  //切换电平状态
	return 0;
}

//定时中断回调函数
ADI_CALLBACK callback_TIM0(void)
{
	adi_gpio_Toggle(Port0,Pin8);  //切换电平状态
	return 0;
}

ADI_CALLBACK callback_UART0(void)
{
//	adi_gpio_Toggle(Port0,Pin0);  //切换电平状态
	return 0;
}

ADI_CALLBACK callback_SPI2(void)
{
//	adi_gpio_Toggle(Port0,Pin0);  //切换电平状态
	return 0;
}

void init_XINT(void)
{
	adi_xint_Init(&XINT_MemorySize,ADI_XINT_MEMORY_SIZE);
	adi_xint_EnableIRQ(ADI_XINT_EVENT_INT0,ADI_XINT_IRQ_FALLING_EDGE); //下降沿触发
	adi_xint_RegisterCallback(ADI_XINT_EVENT_INT0,callback_XINT0(),NULL);
}

void init_TIM(void)
{	
	adi_tmr_Init(ADI_TMR_DEVICE_GP0,callback_TIM0(),NULL,true);  //回调函数定时中断
	ADI_TMR_CONFIG config_TIM0;
	
	config_TIM0.bCountingUp=true;  //是否向上计数
	config_TIM0.bPeriodic=false;  //计数值 输入或自由运行（0xffff）
	config_TIM0.ePrescaler=ADI_TMR_PRESCALER_1;  //分频值  每1个时钟源计数一次
	config_TIM0.eClockSource=ADI_TMR_CLOCK_PCLK; //时钟源 PCLK 26MHz
	config_TIM0.nLoad=26000;  //26个计数 1us
//	config_TIM0.nAsyncLoad=5000;  //异步计数值
	config_TIM0.bReloading=true;  //开启自动重载（到达计数值清零） 开启bPeriodic时有效
	config_TIM0.bSyncBypass=true;  //开启同步旁路	
	adi_tmr_ConfigTimer(ADI_TMR_DEVICE_GP0,&config_TIM0);  //在定时器未开启时使用
	
	adi_tmr_Enable(ADI_TMR_DEVICE_GP0,true);
	
	adi_tmr_Reload(ADI_TMR_DEVICE_GP0);	
}

void init_I2C(void)
{
//	uint32_t HwErrors_I2C0;
	ADI_I2C_HANDLE handle_I2C0;
	adi_i2c_Open(0,&I2C_MemorySize,ADI_I2C_MEMORY_SIZE,&handle_I2C0);
	
	ADI_I2C_TRANSACTION transaction_I2C0;
	uint8_t Data_I2C0 = 0;
	transaction_I2C0.pPrologue = 0;
	transaction_I2C0.nPrologueSize=0;
	transaction_I2C0.pData=&Data_I2C0;
	transaction_I2C0.nDataSize=1;
	transaction_I2C0.bReadNotWrite=true;
	transaction_I2C0.bRepeatStart=false;
	
	adi_i2c_SubmitBuffer(handle_I2C0,&transaction_I2C0);  //非阻塞
	
//	adi_i2c_ReadWrite(handle_I2C0,&transaction_I2C0,HwErrors_I2C0);  //阻塞
	
	adi_i2c_Reset(handle_I2C0);
	adi_i2c_SetBitRate(handle_I2C0,115200);
	adi_i2c_SetSlaveAddress(handle_I2C0,0x48);
//	adi_i2c_IssueGeneralCall(handle_I2C0,pData_I2C0,1,&HwErrors_I2C0);
	adi_i2c_SetBusClear(handle_I2C0,false,true);
	
	uint32_t DataCount_I2C0;
	adi_i2c_GetNumberOfDataProcessed(handle_I2C0,&DataCount_I2C0);
}

void init_UART(void)
{	
	ADI_UART_HANDLE handle_UART0;
	adi_uart_Open(0,ADI_UART_DIR_BIDIRECTION,&UART_MemorySize,ADI_UART_BIDIR_MEMORY_SIZE,&handle_UART0);
	
	uint16_t pBuffer_TX;  //发送
	uint16_t pBuffer_RX;  //接收
	adi_uart_SubmitTxBuffer(handle_UART0,&pBuffer_TX,1,true);  //非阻塞发送
	adi_uart_SubmitRxBuffer(handle_UART0,&pBuffer_RX,1,true);  //非阻塞接收
	
	adi_uart_EnableLoopBack(handle_UART0,true);
	
	uint32_t* pAutobaudErrors_UART0;
	adi_uart_EnableAutobaud(handle_UART0,true,pAutobaudErrors_UART0);
	
	adi_uart_SetRxFifoTriggerLevel(handle_UART0,ADI_UART_RX_FIFO_TRIG_LEVEL_1BYTE);
	adi_uart_EnableFifo(handle_UART0,true);
	
	adi_uart_SetConfiguration(handle_UART0,ADI_UART_NO_PARITY,ADI_UART_ONE_STOPBIT,ADI_UART_WORDLEN_8BITS);  //0校验 1停止 8带宽
	
	adi_uart_FlushTxFifo(handle_UART0);
	adi_uart_FlushRxFifo(handle_UART0);
	
	adi_uart_RegisterCallback(handle_UART0,callback_UART0(),NULL);
}

void init_SPI(void)
{
	ADI_SPI_HANDLE handle_SPI2;
	adi_spi_Open(2,&SPI_MemorySize,ADI_SPI_MEMORY_SIZE,&handle_SPI2);
	ADI_SPI_TRANSCEIVER Xfr_SPI2;
	
	uint8_t pTransmitter;
	uint8_t pReceiver;
	Xfr_SPI2.pTransmitter=&pTransmitter;
	Xfr_SPI2.pReceiver=&pReceiver;
	Xfr_SPI2.TransmitterBytes=1;
	Xfr_SPI2.ReceiverBytes=1;
	Xfr_SPI2.nTxIncrement=0;
	Xfr_SPI2.nRxIncrement=0;
	Xfr_SPI2.bDMA=true;
	Xfr_SPI2.bRD_CTL=true;
	adi_spi_MasterReadWrite(handle_SPI2,&Xfr_SPI2);
	
	adi_spi_SetMasterMode(handle_SPI2,true);
//	adi_spi_SlaveReadWrite(handle_SPI2,&Xfr_SPI2);
	adi_spi_MasterSubmitBuffer(handle_SPI2,&Xfr_SPI2);
//	adi_spi_SlaveSubmitBuffer(handle_SPI2,&Xfr_SPI2);
	adi_spi_RegisterCallback(handle_SPI2,callback_SPI2(),NULL);
	adi_spi_SetClockPhase(handle_SPI2,true);
	adi_spi_SetClockPolarity(handle_SPI2,true);
	bool bComplete;
	adi_spi_isBufferAvailable(handle_SPI2,&bComplete);
	adi_spi_SetContinuousMode(handle_SPI2,true);
	adi_spi_SetLoopback(handle_SPI2,true);
	adi_spi_SetIrqmode(handle_SPI2,0);
	adi_spi_SetReceiveOverflow(handle_SPI2,true);
	adi_spi_SetTransmitUnderflow(handle_SPI2,true);
	adi_spi_SetBitrate(handle_SPI2,115200);
	adi_spi_SetChipSelect(handle_SPI2,ADI_SPI_CS0);
}

void play_NOTE(uint32_t freq_t,float play_time)
{
	int i=24.0/25.0*play_time*2*freq_t/100000;	
	int j=1.0/25.0*play_time*1000;
	while(i--)
	{
		adi_gpio_Toggle(Port0,Pin8);
		delay_us(100000000000/freq_t/2);
	}
	delay_ms(j);
}

void GYZ(void)
{
	delay_ms(1000*NOTE_8);play_NOTE(A4,NOTE_16);play_NOTE(B4,NOTE_16);
	
	play_NOTE(C5,NOTE_16);play_NOTE(D5,NOTE_16);play_NOTE(B4,NOTE_16);play_NOTE(C5,NOTE_16);
	play_NOTE(C5,NOTE_8);play_NOTE(C5,NOTE_16);play_NOTE(B4,NOTE_16);
	play_NOTE(C5,NOTE_16);play_NOTE(D5,NOTE_16);play_NOTE(B4,NOTE_16);play_NOTE(C5,NOTE_16);
	play_NOTE(C5,NOTE_8);play_NOTE(C5,NOTE_16);play_NOTE(D5,NOTE_16);
	
	play_NOTE(E5,NOTE_16);play_NOTE(D5,NOTE_16);play_NOTE(E5,NOTE_16);play_NOTE(D5,NOTE_16);
	play_NOTE(E5,NOTE_8);play_NOTE(E5,NOTE_16);play_NOTE(D5,NOTE_16);
	play_NOTE(E5,NOTE_8);play_NOTE(G5,NOTE_8);
	play_NOTE(E5,NOTE_8);play_NOTE(A4,NOTE_16);play_NOTE(B4,NOTE_16);
	
	play_NOTE(C5,NOTE_16);play_NOTE(D5,NOTE_16);play_NOTE(B4,NOTE_16);play_NOTE(C5,NOTE_16);
	play_NOTE(C5,NOTE_8);play_NOTE(C5,NOTE_16);play_NOTE(B4,NOTE_16);
	play_NOTE(C5,NOTE_16);play_NOTE(D5,NOTE_16);play_NOTE(B4,NOTE_16);play_NOTE(C5,NOTE_16);
	play_NOTE(C5,NOTE_8);play_NOTE(C5,NOTE_16);play_NOTE(D5,NOTE_16);

	play_NOTE(E5,NOTE_16);play_NOTE(D5,NOTE_16);play_NOTE(E5,NOTE_16);play_NOTE(D5,NOTE_16);
	play_NOTE(E5,NOTE_8);play_NOTE(E5,NOTE_16);play_NOTE(D5,NOTE_16);
	play_NOTE(E5,NOTE_8);play_NOTE(G5,NOTE_8);
	play_NOTE(E5,NOTE_8);play_NOTE(G5,NOTE_8);
	
	play_NOTE(E5,NOTE_8*1.5);play_NOTE(G5,NOTE_16);
	play_NOTE(E5,NOTE_8*1.5);play_NOTE(G5,NOTE_16);
	play_NOTE(E5,NOTE_16);play_NOTE(G5,NOTE_16);play_NOTE(A5,NOTE_16);play_NOTE(E5,NOTE_16);
	play_NOTE(G5,NOTE_8);play_NOTE(G5,NOTE_8);
	
	play_NOTE(E5,NOTE_8*1.5);play_NOTE(G5,NOTE_16);
	play_NOTE(E5,NOTE_8*1.5);play_NOTE(G5,NOTE_16);
	play_NOTE(E5,NOTE_16);play_NOTE(G5,NOTE_16);play_NOTE(A5,NOTE_16);play_NOTE(E5,NOTE_16);
	play_NOTE(G5,NOTE_8);play_NOTE(G5,NOTE_16);play_NOTE(G5,NOTE_16);
	
	play_NOTE(E5,NOTE_8);play_NOTE(D5,NOTE_8);
	play_NOTE(D5,NOTE_8);play_NOTE(C5,NOTE_16);play_NOTE(E5,NOTE_16+NOTE_8);play_NOTE(D5,NOTE_8);
	play_NOTE(D5,NOTE_8);play_NOTE(C5,NOTE_16);play_NOTE(A4,NOTE_16+NOTE_4);
	
	delay_ms(NOTE_2*1000);
	delay_ms(1000*NOTE_8);play_NOTE(G5,NOTE_16);play_NOTE(G5,NOTE_16);
	
	play_NOTE(E5,NOTE_8);play_NOTE(D5,NOTE_8);
	play_NOTE(D5,NOTE_8);play_NOTE(C5,NOTE_16);play_NOTE(E5,NOTE_16+NOTE_8);play_NOTE(D5,NOTE_8);
	play_NOTE(D5,NOTE_8);play_NOTE(C5,NOTE_16);play_NOTE(A4,NOTE_16+NOTE_4);
	
	delay_ms(1000*NOTE_4*3);
}

void init_PWR(void)
{
	adi_pwr_Init();
	adi_pwr_SetClockDivider(ADI_CLOCK_HCLK,1);
	adi_pwr_SetClockDivider(ADI_CLOCK_PCLK,1);
}

void init_DMA(void)
{
	adi_dma_Init();
	adi_dma_Enable(true);
}


int main(void)
{
	MUSIC_BPM=70;
	init_PWR();
	init_DMA();
	delay_ms(10);
	delay_us(10);	
	printf("Hello, world!\n");
	init_GPIO();
	P0_BUS_O(0xffff);	
	init_TIM();
	init_XINT();
//	init_UART();
	init_I2C();
	init_SPI();
	P0_BUS_O(0xffff);	
	int i=0;
	while(1)
	{
		//play_NOTE(C9,NOTE_16);
		delay_ms(1000);
		if (P2_I(9)==0){adi_gpio_Toggle(Port0,Pin8);adi_gpio_Toggle(Port0,Pin13);GYZ();}
		i++;
		printf("%d\n",i);}		
}

